package org.circedroid.core;

import java.text.DecimalFormat;
import java.util.Iterator;
import java.util.Set;
import java.util.Vector;

import org.circedroid.activity.R;

import android.util.Log;
import android.widget.Toast;


public class point {
private double X;
private double Y;
private double Z;
private double lon;
private double lat;
private double H;
private Double ell2alt=null;
public Double getEll2alt() {
	return ell2alt;
}
public void setEll2alt(Double ell2alt) {
	this.ell2alt = ell2alt;
}

private Integer lgo;
public Integer getLgo() {
	return lgo;
}
public void setLgo(Integer lgo) {
	this.lgo = lgo;
}
public double getHa() {
	return Ha;
}
public void setHa(double H) {
	this.Ha = H;
}

private double Ha;
private double Easting;
private double Northing;
private Integer reg;
private Integer rea;
private Integer unit;
public Integer getUnit() {
	return unit;
}
public void setUnit(Integer unit) {
	this.unit = unit;
}

private Integer typcoor; //01=cart, 02=geo, 03=proj
private Integer proj;

public double getX() {
	return X;
}
public void setX(double x) {
	X = x;
}
public double getY() {
	return Y;
}
public void setY(double y) {
	Y = y;
}
public double getZ() {
	return Z;
}
public void setZ(double z) {
	Z = z;
}
public double getLon() {
	return lon;
}
public void setLon(double lon) {
	this.lon = lon;
}
public double getLat() {
	return lat;
}
public void setLat(double lat) {
	this.lat = lat;
}
public double getH() {
	return H;
}
public void setH(double h) {
	H = h;
}
public double getEasting() {
	return Easting;
}
public void setEasting(double easting) {
	Easting = easting;
}
public double getNorthing() {
	return Northing;
}
public void setNorthing(double northing) {
	Northing = northing;
}
public Integer getReg() {
	return reg;
}
public void setReg(Integer reg) {
	this.reg = reg;
}
public Integer getRea() {
	return rea;
}
public void setRea(Integer rea) {
	this.rea = rea;
}
public Integer getTypcoor() {
	return typcoor;
}
public void setTypcoor(Integer typcoor) {
	this.typcoor = typcoor;
}
public Integer getProj() {
	return proj;
}
public void setProj(Integer prc) {
	this.proj = prc;
}
public void Proj2Geo(Data donnee){
	

	double ec=donnee.listELG.get(donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getELG()).getEc();
	double e=Math.sqrt(ec);
	double a=donnee.listELG.get(donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getELG()).getA();
	double n=0;
	double Ro=0;
	double C=0;
	double X0=0;
	double Y0=0;
	double l0=0;
	double p0=0;
	double k0=0;
	double p1=0;
	double p2=0;
	double Xp=0;
	double Yp=0;
	double eps,T,N,D;
	double dlgo=donnee.listLGO.get(donnee.listPRC.get(donnee.listPROJ.get(this.getProj()).getPRC()).getLGO()).getValue();
	switch (donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getType()) {

	case 1: //lambert

		switch (donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getMode()) {
		case 2: //avec facteur d'échelle
				
				X0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getX0();
				Y0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getY0();
				l0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getL0();
				p0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ0();
				k0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getDelta();
				
				n=Math.sin(p0);
				double N0=a/Math.sqrt(1-ec*Math.pow(Math.sin(p0), 2.0));
				Ro=N0*k0/Math.tan(p0);
				double L0=Math.log(Math.tan(Math.PI/4.0+p0/2)*Math.pow((1-e*Math.sin(p0))/(1+e*Math.sin(p0)), e/2));
				C=Ro*Math.exp(n*L0);
				
				Xp=X0;
				Yp=Y0+Ro;
				

			break;
		case 3: //secant
			X0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getX0();
			Y0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getY0();
			l0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getL0();
			p0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ0();
			p1=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ1();
			p2=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ2();
			
			double N1=a/Math.sqrt(1-ec*Math.pow(Math.sin(p1), 2.0));
			double N2=a/Math.sqrt(1-ec*Math.pow(Math.sin(p2), 2.0));
			double L1=Math.log(Math.tan(Math.PI/4.0+p1/2)*Math.pow((1-e*Math.sin(p1))/(1+e*Math.sin(p1)), e/2));
			double L2=Math.log(Math.tan(Math.PI/4.0+p2/2)*Math.pow((1-e*Math.sin(p2))/(1+e*Math.sin(p2)), e/2));
			double L3=Math.log(Math.tan(Math.PI/4.0+p0/2)*Math.pow((1-e*Math.sin(p0))/(1+e*Math.sin(p0)), e/2));
			
			n=Math.log((N2*Math.cos(p2))/(N1*Math.cos(p1)))/(L1-L2);
			C=N1*Math.cos(p1)/n*Math.exp(n*L1);
			Ro=C*Math.exp(-n*L3);
			
			Xp=X0;
			Yp=Y0+Ro;

			break;
		}
		this.lon=l0+Math.atan2(this.Easting-Xp,Yp-this.Northing)/n+dlgo;
		double L=-1.0/n*Math.log(Math.sqrt(Math.pow(this.Northing-Yp,2.0)+Math.pow(this.Easting-Xp,2.0))/C);
		double latold;
		this.lat=2*Math.atan(Math.exp(L))-Math.PI/2.0;
		for (int i=1;i<10;i++){
			latold=this.lat;
			this.lat=2*Math.atan(Math.pow((1+e*Math.sin(latold))/(1-e*Math.sin(latold)), e/2.0)*Math.exp(L))-Math.PI/2.0;
			if (Math.abs(this.lat-latold)<0.000000001){
				break;
			}
		}
		
		break;
	case 2: //UTM
		
		X0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getX0();
		Y0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getY0();
		l0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getL0();
		p0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ0();
		k0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getDelta();
		
		
		double tmp = Math.sqrt(1-ec);
		double eOne = (1.0-tmp)/(1.0+tmp);
		double M0 = a * ((1.0-ec*(1.0/4.0+ec*(3.0/64.0+ec*5.0/256.0)))*p0-ec*(3.0/8.0+ec*(3.0/32.0+ec*45.0/1024.0))*Math.sin(2.0*p0)+ec*ec*(15.0/256.0+ec*45.0/1024.0)*Math.sin(4.0*p0)-35.0/3072.0*ec*ec*ec*Math.sin(6.0*p0));
		double M=M0+(this.Northing-Y0)/k0;
		double mu = M/(a*(1.0-ec*(0.25+ec*(3.0/64.0+ec*5.0/256.0))));
		double lat1 = mu
				+ (1.5*eOne-27.0/32.0*eOne*eOne*eOne)*Math.sin(2.0*mu)
				+ eOne*eOne*(21.0/16.0-55.0/32.0*eOne*eOne)*Math.sin(4.0*mu)
				+ eOne*eOne*eOne*151.0/96.0*Math.sin(6.0*mu)
				+ 1097.0*eOne*eOne*eOne*eOne/512.0*Math.sin(8.0*mu);
		if (Math.abs(Math.abs(lat1)-Math.PI*0.5)<1D-8){
			this.lon = l0;
			if ((this.Northing-Y0)>0.0) {
				this.lat=Math.PI*0.5;
			} else {
				this.lat=-0.5*Math.PI;
			}
			break;
		}
		
		eps = ec/(1.0-ec);
		C = eps*Math.pow(Math.cos(lat1), 2.0);
		T = Math.pow(Math.tan(lat1),2.0);
		N = a/Math.sqrt(1.0-ec*Math.pow(Math.sin(lat1), 2.0));
		Ro = a*(1.0-ec)/Math.pow(1.0-ec*Math.pow(Math.sin(lat1), 2.0), 1.5);
		D = (this.Easting-X0)/(N*k0);
		
		this.lat = lat1+dlgo-(N*Math.tan(lat1)/Ro)*(D*D*(0.5-D*D*((5.0+3.0*T+10.0*C-4.0*C*C-9.0*eps)/24.0+D*D*(61.0+90.0*T+298.0*C+45.0*T*T-252.0*eps-3.0*C*C)/720.0)));
		this.lon = l0+D*(1.0-D*D*((1.0+2.0*T+C)/6.0+D*D*(5.0-2.0*C+28.0*T-3.0*C*C+8.0*eps+24.0*T*T)/120.0))/Math.cos(lat1);
		
	}
	double lonmin=donnee.listPROJ.get(this.proj).getLonMin();
	double lonmax=donnee.listPROJ.get(this.proj).getLonMax();
	double latmin=donnee.listPROJ.get(this.proj).getLatMin();
	double latmax=donnee.listPROJ.get(this.proj).getLatMax();
	if (this.lon>lonmax  || this.lon<lonmin  || this.lat>latmax  || this.lat<latmin) {
		Toast.makeText(donnee.context, "Conversion hors zone de la projection", Toast.LENGTH_SHORT).show();
	}
}
public void Geo2Cart(Data donnee){
	//OK
	double a;
	double ec;
	Integer numelg= donnee.listREG.get(this.getReg()).getELG();
	a= donnee.listELG.get(numelg).getA();
	ec= donnee.listELG.get(numelg).getEc();
	double N= a/Math.sqrt(1-ec*Math.pow(Math.sin(this.lat),2));
	this.X=(N+this.H)*Math.cos(this.lon)*Math.cos(this.lat);
	this.Y=(N+this.H)*Math.sin(this.lon)*Math.cos(this.lat);
	this.Z=(N*(1-ec)+this.H)*Math.sin(this.lat);
}
public void Cart2Geo(Data donnee){
	//OK
	double a;
	double f;
	double ec;
	Integer numelg= donnee.listREG.get(this.getReg()).getELG();
	a= donnee.listELG.get(numelg).getA();
	f= donnee.listELG.get(numelg).getF();
	ec=donnee.listELG.get(numelg).getEc();
	double R,mu;
	R=Math.sqrt(this.X*this.X+this.Y*this.Y+this.Z*this.Z);
	mu=Math.atan(this.Z/Math.sqrt(this.X*this.X+this.Y*this.Y)*(1-f+ec*a/R));
	this.lon=2*Math.atan((this.Y)/(Math.sqrt(this.X*this.X+this.Y*this.Y)+this.X));
	this.lat=Math.atan((this.Z*(1-f)+ec*a*Math.pow(Math.sin(mu),3))/((1-f)*(Math.sqrt(this.X*this.X+this.Y*this.Y)-ec*a*Math.pow(Math.cos(mu),3))));
	this.H=Math.sqrt(this.X*this.X+this.Y*this.Y)*Math.cos(this.lat)+this.Z*Math.sin(this.lat)-a*Math.sqrt(1-ec*Math.pow(Math.sin(this.lat), 2));
	try {
		this.lon-=donnee.listLGO.get(getLgo()).getValue();
	}
	catch (Exception e){
		
	}
}
public void Geo2Proj(Data donnee){
	
	double lonmin=donnee.listPROJ.get(this.proj).getLonMin();
	double lonmax=donnee.listPROJ.get(this.proj).getLonMax();
	double latmin=donnee.listPROJ.get(this.proj).getLatMin();
	double latmax=donnee.listPROJ.get(this.proj).getLatMax();
	if (this.lon>lonmax  || this.lon<lonmin  || this.lat>latmax  || this.lat<latmin) {
		Toast.makeText(donnee.context, "Conversion hors zone de la projection", Toast.LENGTH_LONG).show();
	}
	//Valeur de debug pour le moment
	double ec=donnee.listELG.get(donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getELG()).getEc();
	double e=Math.sqrt(ec);
	double a=donnee.listELG.get(donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getELG()).getA();
	double n;
	double Ro;
	double C;
	double X0;
	double Y0;
	double l0,p0,k0,p1,p2;
	double Xp;
	double Yp;	
	double dlgo=donnee.listLGO.get(donnee.listPRC.get(donnee.listPROJ.get(this.getProj()).getPRC()).getLGO()).getValue();
	
	switch (donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getType()) {

	case 1: //lambert

		switch (donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getMode()) {
		case 2: //avec facteur d'échelle
				
				X0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getX0();
				Y0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getY0();
				l0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getL0();
				p0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ0();
				k0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getDelta();
				
				n=Math.sin(p0);
				double N0=a/Math.sqrt(1-ec*Math.pow(Math.sin(p0), 2.0));
				Ro=N0*k0/Math.tan(p0);
				double L0=Math.log(Math.tan(Math.PI/4.0+p0/2)*Math.pow((1-e*Math.sin(p0))/(1+e*Math.sin(p0)), e/2));
				C=Ro*Math.exp(n*L0);
				
				Xp=X0;
				Yp=Y0+Ro;
				double L=Math.log(Math.tan(Math.PI/4.0+this.lat/2)*Math.pow((1-e*Math.sin(this.lat))/(1+e*Math.sin(this.lat)), e/2));
				this.Easting=Xp+C*Math.exp(-n*L)*Math.sin(n*(this.lon-dlgo-l0));
				this.Northing=Yp-C*Math.exp(-n*L)*Math.cos(n*(this.lon-dlgo-l0));
			break;
		case 3: //secant
			X0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getX0();
			Y0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getY0();
			l0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getL0();
			p0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ0();
			p1=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ1();
			p2=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ2();
			
			double N1=a/Math.sqrt(1-ec*Math.pow(Math.sin(p1), 2.0));
			double N2=a/Math.sqrt(1-ec*Math.pow(Math.sin(p2), 2.0));
			double L1=Math.log(Math.tan(Math.PI/4.0+p1/2)*Math.pow((1-e*Math.sin(p1))/(1+e*Math.sin(p1)), e/2));
			double L2=Math.log(Math.tan(Math.PI/4.0+p2/2)*Math.pow((1-e*Math.sin(p2))/(1+e*Math.sin(p2)), e/2));
			double L3=Math.log(Math.tan(Math.PI/4.0+p0/2)*Math.pow((1-e*Math.sin(p0))/(1+e*Math.sin(p0)), e/2));
			
			n=Math.log((N2*Math.cos(p2))/(N1*Math.cos(p1)))/(L1-L2);
			C=N1*Math.cos(p1)/n*Math.exp(n*L1);
			Ro=C*Math.exp(-n*L3);
			
			Xp=X0;
			Yp=Y0+Ro;
			double LL=Math.log(Math.tan(Math.PI/4.0+this.lat/2)*Math.pow((1-e*Math.sin(this.lat))/(1+e*Math.sin(this.lat)), e/2));
			this.Easting=Xp+C*Math.exp(-n*LL)*Math.sin(n*(this.lon-dlgo-l0));
			this.Northing=Yp-C*Math.exp(-n*LL)*Math.cos(n*(this.lon-dlgo-l0));
			break;
		}
		
		break;
	case 2: //UTM
		
		X0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getX0();
		Y0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getY0();
		l0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getL0();
		p0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getJ0();
		k0=donnee.listPRC.get(donnee.listPROJ.get(this.proj).getPRC()).getDelta();
		
		double eps = ec/(1.0-ec);
		double N = a/Math.sqrt(1.0-ec*Math.pow(Math.sin(this.lat), 2.0));
		double T = Math.pow(Math.tan(this.lat),2.0);
		C = eps*Math.pow(Math.cos(this.lat), 2.0);
		double A = Math.cos(this.lat)*(this.lon-dlgo-l0);
		double M = a * ((1.0-ec*(1.0/4.0+ec*(3.0/64.0+ec*5.0/256.0)))*this.lat-ec*(3.0/8.0+ec*(3.0/32.0+ec*45.0/1024.0))*Math.sin(2.0*this.lat)+ec*ec*(15.0/256.0+ec*45.0/1024.0)*Math.sin(4.0*this.lat)-35.0/3072.0*ec*ec*ec*Math.sin(6.0*this.lat));
		double M0 = a * ((1.0-ec*(1.0/4.0+ec*(3.0/64.0+ec*5.0/256.0)))*p0-ec*(3.0/8.0+ec*(3.0/32.0+ec*45.0/1024.0))*Math.sin(2.0*p0)+ec*ec*(15.0/256.0+ec*45.0/1024.0)*Math.sin(4.0*p0)-35.0/3072.0*ec*ec*ec*Math.sin(6.0*p0));
		
		this.Easting=X0+k0*N*A*(1.0+A*A/6.0*((1.0-T+C)+A*A/20.0*(5.0-18.0*T+T*T+72.0*C-58.0*eps)));
		this.Northing=Y0+k0*(M-M0+N*Math.tan(this.lat)*(A*A*(0.5+A*A*((5.0-T+C*(9.0+4.0*C))/24.0+A*A/720.0*(61.0-58.0*T*T+600.0*C-330*eps)))));
		break;
	}
}

public point convertFrom(point Pdep, Data donnee){
	
	if (Pdep.getRea()>0){
		if (donnee.listREG.get(Pdep.getReg()).getDim()==(short) 3){
			//On peut déterminer une hauteur ellipsoidale
			for (int i=1;i<=donnee.listGR1D.size();i++){
				for (int j=1;j<=donnee.listGR1D.get(i).getListREA().size();j++){
					if (((int) Pdep.getRea())==((int) donnee.listGR1D.get(i).getListREA().get(j))){
						Double lonn;
						Double latt;
						point ptps=new point();
						ptps.setLgo(donnee.getLgoNum("Greenwich"));
						ptps.setReg(donnee.listGR1D.get(i).getREG());
						ptps.setTypcoor(2);
						ptps.setUnit(1);
						Integer reapdep=Pdep.getRea();
						Pdep.setRea(0);
						ptps.convertFrom(Pdep, donnee);
						Pdep.setRea(reapdep);
						lonn=ptps.getLon();
						latt=ptps.getLat();
						Pdep.setEll2alt(donnee.listGR1D.get(i).getValue(lonn, latt));
						if (Pdep.getEll2alt()!=null){
							Pdep.setH(Pdep.getHa()+Pdep.getEll2alt());
						}
						else {
							Pdep.setRea(-1);
							this.setRea(-1);
							
							Toast.makeText(donnee.context, "Départ : "+donnee.context.getString(R.string.outgridalti), Toast.LENGTH_SHORT).show();
						}
					}
				}
			}
			
		} else {
			//Pdep.setH(0);
			Pdep.setRea(-1);
			this.setRea(-1);
		}
	}
		
	//Il faut les coord cart
			switch (Pdep.getTypcoor()){
			case 1 : //Wonderfull, nothing to do :)
				//Pdep.Cart2Geo(donnee);
				break;
			case 2 :
				
				Pdep.Geo2Cart(donnee);
				break;
			case 3 : Pdep.Proj2Geo(donnee);
					 Pdep.Geo2Cart(donnee);
			    break;
			}
	
	if (Pdep.getReg()!=this.getReg() && donnee.listREG.get(Pdep.getReg()).getELG()!=donnee.listREG.get(this.getReg()).getELG()){
		//Référentiels différents => similitude 7 Param.
		
		
		//on a les coord cart
		double ex=0,ey=0,ez=0;
		double tx=0, ty=0, tz=0;
		double d=0;
		Set<Integer> regset=donnee.listTSG.keySet();
		Iterator<Integer> iter=regset.iterator();
		Integer current;
		Boolean findTSG =false;
		for (int i=0;i<donnee.listTSG.size();i++){
			current=iter.next();
			if (donnee.listTSG.get(current).getReg1()==Pdep.getReg() && donnee.listTSG.get(current).getReg2()==this.getReg()){
				tx=donnee.listTSG.get(current).getTX0();
				ty=donnee.listTSG.get(current).getTY0();
				tz=donnee.listTSG.get(current).getTZ0();
				ex=donnee.listTSG.get(current).getRX();
				ey=donnee.listTSG.get(current).getRY();
				ez=donnee.listTSG.get(current).getRZ();
				d=donnee.listTSG.get(current).getEch();
				findTSG = true;
				break;
			}
			if (donnee.listTSG.get(current).getReg1()==this.getReg() && donnee.listTSG.get(current).getReg2()==Pdep.getReg()){
				tx=-donnee.listTSG.get(current).getTX0();
				ty=-donnee.listTSG.get(current).getTY0();
				tz=-donnee.listTSG.get(current).getTZ0();
				ex=-donnee.listTSG.get(current).getRX();
				ey=-donnee.listTSG.get(current).getRY();
				ez=-donnee.listTSG.get(current).getRZ();
				d=-donnee.listTSG.get(current).getEch();
				findTSG = true;
				break;
			}
		}
		if (findTSG){
			this.X=tx+(1+d)*Pdep.getX()+ez*Pdep.getY()-ey*Pdep.getZ();
			this.Y=ty+(1+d)*Pdep.getY()-ez*Pdep.getX()+ex*Pdep.getZ();
			this.Z=tz+(1+d)*Pdep.getZ()+ey*Pdep.getX()-ex*Pdep.getY();
		} else {
			iter=donnee.listTSG0.keySet().iterator();
			Vector<Double> trans;
			for (int i=0;i<donnee.listTSG0.size();i++){
				current=iter.next();
				if (Pdep.getReg()==donnee.listTSG0.get(current).getReg2() && this.getReg()==donnee.listTSG0.get(current).getReg1()){
					//Youpi, sens simple
					//On cherche la GR3D correspondante
					GR3D currentGR3D = null;
					Iterator<Integer> iterbis =donnee.listGR3D.keySet().iterator();
					Integer currentbis;
					for (int j=0;j<donnee.listGR3D.size();j++){
						currentbis = iterbis.next();
						if (donnee.listTSG0.get(current).getReg1()==donnee.listGR3D.get(currentbis).getReg1() && donnee.listTSG0.get(current).getReg2()==donnee.listGR3D.get(currentbis).getReg2()){
							currentGR3D = donnee.listGR3D.get(currentbis);
						}
					}
					if (currentGR3D == null){
						return null;
					}
					Pdep.Cart2Geo(donnee);
					trans = currentGR3D.getValue(Pdep.lon, Pdep.lat);
					
					this.X=Pdep.X - trans.get(0);
					this.Y=Pdep.Y - trans.get(1);
					this.Z=Pdep.Z - trans.get(2);
					
					
				}
				if (Pdep.getReg()==donnee.listTSG0.get(current).getReg1() && this.getReg()==donnee.listTSG0.get(current).getReg2()){
					//Sens moins cool
					//On cherche la GR3D correspondante
					GR3D currentGR3D = null;
					Iterator<Integer> iterbis =donnee.listGR3D.keySet().iterator();
					Integer currentbis;
					for (int j=0;j<donnee.listGR3D.size();j++){
						currentbis = iterbis.next();
						if (donnee.listTSG0.get(current).getReg1()==donnee.listGR3D.get(currentbis).getReg1() && donnee.listTSG0.get(current).getReg2()==donnee.listGR3D.get(currentbis).getReg2()){
							currentGR3D = donnee.listGR3D.get(currentbis);
						}
					}
					if (currentGR3D == null){
						return null;
					}
					//Utilisation de la transfo approchée
					trans = donnee.listTSG0.get(current).getVect();
					Vector<Double> transold;
					for (int n=1;n<=15;n++){
						this.X=Pdep.X + trans.get(0);
						this.Y=Pdep.Y + trans.get(1);
						this.Z=Pdep.Z + trans.get(2);
						this.Cart2Geo(donnee);
						transold=trans;
						trans = currentGR3D.getValue(this.lon, this.lat);
						double diff = (trans.get(0)-transold.get(0))*(trans.get(0)-transold.get(0))+(trans.get(1)-transold.get(1))*(trans.get(1)-transold.get(1))+(trans.get(2)-transold.get(2))*(trans.get(2)-transold.get(2));
						Log.d("moi", "Iter "+n+", var "+diff);
						if (diff < 0.0005*0.0005){
							break;
						}
					}
					this.X=Pdep.X + trans.get(0);
					this.Y=Pdep.Y + trans.get(1);
					this.Z=Pdep.Z + trans.get(2);
					 
					
					
					
				}
			}
		}
	}
	else {
		//Même ref/ellip
		this.X=Pdep.getX();
		this.Y=Pdep.getY();
		this.Z=Pdep.getZ();
	}
	
	
	//Là on a les coord cart
	
	switch (this.getTypcoor()){
	case 1 : //Wonderfull, nothing to do :)
		break;
	case 2 : this.Cart2Geo(donnee);
		break;
	case 3 : this.Cart2Geo(donnee);
			 this.Geo2Proj(donnee);
	    break;
	}
	

	if (this.getRea()>0){
		if (((int) this.rea) == ((int) Pdep.getRea())){
			this.Ha=Pdep.getHa();
			Log.d("moi","même sysème alti");
			return this;
		} else if (donnee.listREG.get(this.getReg()).getDim()==3 || donnee.listREG.get(Pdep.getReg()).getDim()==3){
			//On peut déterminer une hauteur ellipsoidale
			for (int i=1;i<=donnee.listGR1D.size();i++){
				for (int j=1;j<=donnee.listGR1D.get(i).getListREA().size();j++){
					if (((int) this.getRea())==((int) donnee.listGR1D.get(i).getListREA().get(j))){
							Log.d("moi","je vais convertir");
							Double lonn;
							Double latt;
							point ptps=new point();
							ptps.setLgo(donnee.getLgoNum("Greenwich"));
							ptps.setReg(donnee.listGR1D.get(i).getREG());
							ptps.setTypcoor(2);
							ptps.setUnit(1);
							Integer reapdep=Pdep.getRea();
							Pdep.setRea(0);
							ptps.convertFrom(Pdep, donnee);
							Pdep.setRea(reapdep);
							lonn=ptps.getLon();
							latt=ptps.getLat();
							Log.d("moi",lonn+" "+latt);
							this.setEll2alt(donnee.listGR1D.get(i).getValue(lonn, latt));
							
							if (this.getEll2alt()!=null){
								if (this.reg == donnee.listGR1D.get(i).getREG()){
									this.Cart2Geo(donnee);
									this.setHa(this.getH()-this.getEll2alt());
								}
								else {
									Pdep.Cart2Geo(donnee);
									this.setHa(Pdep.getH()-this.getEll2alt());
								}
							}
							else {
								Log.d("moi","arr : ell2alt null");
								this.setRea(-1);
								Toast.makeText(donnee.context, "Arrivée : "+donnee.context.getString(R.string.outgridalti), Toast.LENGTH_SHORT).show();
							}
						
					}
				}
			}
		} 
		
	}
	
	
	return this;
}

public point(){
	this.X=0;
	this.Y=0;
	this.Z=0;
	this.lon=0;
	this.lat=0;
	this.H=0;
	this.Ha=0;
	this.Easting=0;
	this.Northing=0;
	this.reg=0;
	this.typcoor=0;
	this.proj=0;
	this.rea=0;
	this.lgo=0;
	this.unit=0;
}

private String fixed(Double d, Integer n){
	DecimalFormat df3=new DecimalFormat();
	df3.setMaximumFractionDigits(n);
	df3.setMinimumFractionDigits(n);
	return df3.format(d);
}

public String toString(Data data){
	
	String retour="";
	String signe="";
	switch (typcoor) {
	case 1:
		retour="X = ".concat(fixed(X, 3)).concat(" m\nY = ").concat(fixed(Y, 3)).concat(" m\nZ = ").concat(fixed(Z, 3)).concat(" m");
		break;
	case 2:
		long deg;
		long min;
		double sec;
		
		
		
		switch (unit) {
		case 1:
			retour="Lon = ".concat(fixed(lon,10)).concat(" rad\nLat = ").concat(fixed(lat,10)).concat(" rad");
			break;
		case 2:
			retour="Lon = ".concat(fixed(lon*180.0/Math.PI,8)).concat(" °\nLat = ").concat(fixed(lat*180.0/Math.PI,8)).concat(" °");
			break;
		case 3:
			retour="Lon = ".concat(fixed(lon*200.0/Math.PI,8)).concat(" gon\nLat = ").concat(fixed(lat*200.0/Math.PI,8)).concat(" gon");
			break;
		case 4:
			retour="Lon = ".concat(fixed(lon*12.0/Math.PI,10)).concat(" h\nLat = ").concat(fixed(lat*12.0/Math.PI,10)).concat(" h");
			break;
		case 5:
			retour="Lon = ".concat(fixed(lon*648000.0/Math.PI,5)).concat(" \"\nLat = ").concat(fixed(lat*648000.0/Math.PI,5)).concat(" \"");
			break;
		case 6:
			retour="Lon = ".concat(fixed(lon*43200.0/Math.PI,6)).concat(" s\nLat = ").concat(fixed(lat*43200.0/Math.PI,6)).concat(" s");
			break;
		case 10:
			signe="";
			if (lon<0){
				lon=Math.abs(lon);
				signe="-";
			}
			lon*=180.0/Math.PI;
			deg=(long)lon;
			min=(long)((lon-(double)deg)*60);
			sec=((lon-(double)deg)*60-(double)min)*60;
			retour="Lon = ".concat(signe).concat(Long.toString(deg)).concat("°").concat(Long.toString(min)).concat("'").concat(fixed(sec,5)).concat("\"");
			lat*=180.0/Math.PI;
			signe="";
			if (lat<0){
				lat=Math.abs(lat);
				signe="-";
			}
			deg=(long)lat;
			min=(long)((lat-(double)deg)*60);
			sec=((lat-(double)deg)*60-(double)min)*60;
			retour=retour.concat("\nLat = ").concat(signe).concat(Long.toString(deg)).concat("°").concat(Long.toString(min)).concat("'").concat(fixed(sec,5)).concat("\"");
			break;
		case 11:
			signe="";
			if (lon<0){
				lon=Math.abs(lon);
				signe="-";
			}
			lon*=12.0/Math.PI;
			deg=(long)lon;
			min=(long)((lon-(double)deg)*60);
			sec=((lon-(double)deg)*60-(double)min)*60;
			retour="Lon = ".concat(signe).concat(Long.toString(deg)).concat("h").concat(Long.toString(min)).concat("mn").concat(fixed(sec,6)).concat("s");
			lat*=12.0/Math.PI;
			signe="";
			if (lat<0){
				lat=Math.abs(lat);
				signe="-";
			}
			deg=(long)lat;
			min=(long)((lat-(double)deg)*60);
			sec=((lat-(double)deg)*60-(double)min)*60;
			retour=retour.concat("\nLat = ").concat(signe).concat(Long.toString(deg)).concat("h").concat(Long.toString(min)).concat("mn").concat(fixed(sec,6)).concat("s");
			break;
		case 12:
			signe="";
			if (lon<0){
				lon=Math.abs(lon);
				signe="-";
			}
			lon*=180.0/Math.PI;
			deg=(long)lon;
			sec=((lon-(double)deg)*60);
			retour="Lon = ".concat(signe).concat(Long.toString(deg)).concat("°").concat(fixed(sec,6)).concat("'");
			lat*=180.0/Math.PI;
			signe="";
			if (lat<0){
				lat=Math.abs(lat);
				signe="-";
			}
			deg=(long)lat;
			sec=((lat-(double)deg)*60);
			retour=retour.concat("\nLat = ").concat(signe).concat(Long.toString(deg)).concat("°").concat(fixed(sec,6)).concat("'");
			break;
		}
		
		if (this.rea==0){
			retour=retour.concat("\nHe = ").concat(fixed(H, 3)).concat(" m");
		}
		else if (this.rea>0){
			retour=retour.concat("\nAltitude : ");
			retour=retour.concat(data.listREA.get(this.rea).getNom()).concat("\nHa = ").concat(fixed(Ha, 3)).concat(" m");
		}
			
			
			
			
		break;
	case 3:
		retour="E = ".concat(fixed(Easting, 3)).concat(" m\nN = ").concat(fixed(Northing, 3)).concat(" m\n");
		
		if (this.rea==0){
			retour=retour.concat("\nHe = ").concat(fixed(H, 3)).concat(" m");
		}
		else if (this.rea>0){
			retour=retour.concat("\nAltitude : ");
			retour=retour.concat(data.listREA.get(this.rea).getNom()).concat("\nHa = ").concat(fixed(Ha, 3)).concat(" m");
		}
		
		break;

	default:
		retour="coucou";
		break;
	}
	return retour;
}

public point clone(){
	point retour = new point();
	retour.X=this.X;
	retour.Y=this.Y;
	retour.Z=this.Z;
	retour.lon=this.lon;
	retour.lat=this.lat;
	retour.H=this.H;
	retour.lgo=this.lgo;
	retour.Ha=this.Ha;
	retour.Easting=this.Easting;
	retour.Northing=this.Northing;
	retour.reg=this.reg;
	retour.rea=this.rea;
	retour.unit=this.unit;
	retour.typcoor=this.typcoor;
	retour.proj=this.proj;
	return retour;
}

}
